﻿using Gameplay.PVE;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Object = UnityEngine.Object;

namespace Yoozoo.Modules.Furnitures
{
    /// <summary>
    /// 场景设置
    /// </summary>
    [Serializable]
    public class RoomSceneConfig
    {
        /// <summary>
        /// 保存场景的LightMapSettings, RenderSettings等属性
        /// </summary>
        public SceneRenderData RenderData;

        /// <summary>
        /// 房间内各个MeshRender的路径
        /// </summary>
        public List<string> MeshRendererPaths = new List<string>();

        /// <summary>
        /// 房间内各个MeshRender的光照属性
        /// </summary>
        public List<MeshRendererData> MeshRendererData = new List<MeshRendererData>();
        
        private List<Texture2D> lightMapColors;
        private List<Texture2D> lightMapDirs;
        private Material skyBoxMaterial;
        private Cubemap reflectionProbe;
        private ResLoader lightMapLoader;

        public void LoadAssets(Action action)
        {
            var sceneRenderData = RenderData;
            lightMapLoader = ResLoader.Alloc();
            lightMapColors = new List<Texture2D>();
            lightMapDirs = new List<Texture2D>();

            for (int i = 0; i < sceneRenderData.lightMapColorPath.Count; i++)
            {
                int index = i;
                lightMapColors.Add(null);
                lightMapLoader.Add2Load(sceneRenderData.lightMapColorPath[i], typeof(Texture2D), (success, assetName, asset) =>
                {
                    if (success)
                    {
                        lightMapColors[index] = asset as Texture2D;
                    }
                });
            }

            for (int i = 0; i < sceneRenderData.lightMapDirPath.Count; i++)
            {
                int index = i;
                lightMapDirs.Add(null);
                lightMapLoader.Add2Load(sceneRenderData.lightMapDirPath[i], typeof(Texture2D), (success, assetName, asset) =>
                {
                    if (success)
                    {
                        lightMapDirs[index] = asset as Texture2D;
                    }
                });
            }

            lightMapLoader.Add2Load(sceneRenderData.skyBoxMaterialPath, typeof(Material), (success, assetName, asset) =>
            {
                if (success)
                {
                    skyBoxMaterial = asset as Material;
                }
            });
            
            lightMapLoader.Add2Load(sceneRenderData.reflectionProbePath, typeof(Cubemap), (success, assetName, asset) =>
            {
                if (success)
                {
                    reflectionProbe = asset as Cubemap;
                }
            });

            lightMapLoader.Load(action);
        }

        public void ApplySetting(Transform root)
        {
            var sceneRenderData = RenderData;

            // LightMap
            var sceneLightMap = new LightmapData[lightMapColors.Count];
            for (int i = 0; i < sceneLightMap.Length; i++)
            {
                sceneLightMap[i] = new LightmapData
                {
                    lightmapColor = lightMapColors[i],
                    lightmapDir = lightMapDirs[i],
                };
            }

            LightmapSettings.lightmaps = sceneLightMap;
            LightmapSettings.lightmapsMode = LightmapsMode.CombinedDirectional;

            // Fog
            RenderSettings.fog = sceneRenderData.isFog;
            RenderSettings.fogColor = sceneRenderData.fogColor;
            RenderSettings.fogMode = sceneRenderData.fogMode;
            RenderSettings.fogStartDistance = sceneRenderData.fogStart;
            RenderSettings.fogEndDistance = sceneRenderData.fogEnd + 250;

            // Sky box
            if (skyBoxMaterial)
            {
                RenderSettings.skybox = Object.Instantiate(skyBoxMaterial);
            }

            RenderSettings.ambientLight = sceneRenderData.ambientColor;
            RenderSettings.defaultReflectionMode = sceneRenderData.reflectionMode;
            RenderSettings.ambientMode = sceneRenderData.ambientMode;

            // reflection probe
            if (reflectionProbe)
            {
                RenderSettings.customReflection = reflectionProbe;
                var go = new GameObject("ReflectionProbe");
                go.transform.SetParent(root);
                go.transform.position = Vector3.zero;
                var rp = go.AddComponent<ReflectionProbe>();
                rp.customBakedTexture = reflectionProbe;
                rp.mode = ReflectionProbeMode.Custom;
                rp.size = new Vector3(1000, 1000, 1000);
            }

            // RenderSettings.ambientSkyColor ???
        }

        public void FixMeshRenderers(Transform root)
        {
            foreach (var data in MeshRendererData)
            {
                string path = MeshRendererPaths[data.renderIndex];
                var t = root.Find(path);
                if (t == null)
                    continue;

                var meshRenderer = t.GetComponent<MeshRenderer>();
                if (meshRenderer == null)
                    continue;

                meshRenderer.lightmapIndex = data.lightmapIndex;
                meshRenderer.lightmapScaleOffset = data.lightmapScaleOffset;
            }
        }
    }
}
